package org.teamh.artificialIntelligence;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;

import org.teamh.logic.datamodel.Cell;
import org.teamh.logic.datamodel.TowerDescription;
import org.teamh.logic.datamodel.User;
import org.teamh.logic.datamodel.Waypoint;

public class Initiator {

	private static HashMap<String, ArrayList<Cell>> cellList = new HashMap<String, ArrayList<Cell>>();
	private final static float SLOWTOWER_LEVEL4_RANGE = 2.5f;
	
	private Initiator() {}
	
	public static void getPriorityCells() {
//		//System.out.println("getproiritycells");
		for(TowerDescription t: AIInterfaceManager.datamodelManager.getTowerDescriptions().values()) {
			if(t.getLevel() == 1) {
				fillList(t.getName(), (float)t.getRange());
			}
		}
		
		fillSlowtowerList(SLOWTOWER_LEVEL4_RANGE);
	}
	
	private static void fillSlowtowerList(float range) {
		LinkedList<Cell> temp = new LinkedList<Cell>();
		for(Cell c1 : AIInterfaceManager.user.getUserAssets().getTile().getMap().getCells().values()) {
			if(c1.getType().equals("WALKABLE") && !c1.getSlowed()) {
				Cell best = null;
				for(Cell c2 : cellList.get("Slowtower")) {
					if(c2.getValue() > 1 && getDistance(c2, c1) <= range) {
						if(best == null) {
							best = c2;
						} else if(c2.getValue() < best.getValue()) {
							best = c2;
						}
					}
				}
				if(best != null) {
					for(Cell c2 : AIInterfaceManager.user.getUserAssets().getTile().getMap().getCells().values()) {
						if(!c2.getSlowed()) {
							if(getDistance(c2, best) <= range) {
								c2.setSlowed(true);
								c2.setNearestSlowtowerCell(best);
							}
						}
					}
					best.setNearestSlowtowerCell(best);
					temp.add(best);
				}
			}
		}
		for(Cell c1 : temp) {
			for(TowerDescription t: AIInterfaceManager.datamodelManager.getTowerDescriptions().values()) {
				if(t.getLevel() == 1) {
					@SuppressWarnings("unchecked")
					ArrayList<Cell> cellsToDelete = (ArrayList<Cell>) cellList.get(t.getName()).clone();
					for(Cell c2 : cellsToDelete) {
						if(c2.getID().equals(c1.getID())) {
							cellList.get(t.getName()).remove(c2);
						}
					}
				}
			}
		}
	}

	private static void fillList(String towerName, float range) {
//		//System.out.println("filllist");
		ArrayList<Cell> cells = new ArrayList<Cell>();
		User user = AIInterfaceManager.user;
		
		//fill list
		for(Cell c: user.getUserAssets().getTile().getMap().getCells().values()) {
			if(c.getType().equalsIgnoreCase("TOWER")) {
				float value = 0;
				float towerX = c.getX();
				float towerY = c.getY();
				for(Waypoint w: user.getUserAssets().getTile().getMap().getWaypoints().values()) {
					if(w.getNext() != null) {
						float x = w.getCell().getX();
						float y = w.getCell().getY();
						float a = w.getNext().getCell().getX() - w.getCell().getX();
						float b = w.getNext().getCell().getY() - w.getCell().getY();
						
						float beforeRoot = -(a * (x - towerX) + b * (y - towerY)) / (a * a + b * b);
						float underRoot = beforeRoot * beforeRoot - ((x - towerX) * (x - towerX) + (y - towerY) * (y - towerY) - range * range) / (a * a + b * b); 
						
						if(underRoot > 0) {
							float t1 = beforeRoot + (float)Math.sqrt(underRoot);
							float t2 = beforeRoot - (float)Math.sqrt(underRoot);
							
							if(t1 > t2) {
								float temp = t1;
								t1 = t2;
								t2 = temp;
							}
							
							if(t1 > 1 || t2 < 0) {
								continue;
							}
							
							float start = Math.max(0, t1);
							float end = Math.min(1, t2);
							
							float startX = x + start * a;
							float startY = y + start * b;
							
							float endX = x + end * a;
							float endY = y + end * b;
							
							float distance = (float)Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2));
							float totalDistance = (float)getDistance(w.getCell(), w.getNext().getCell());
							
							value += distance / totalDistance;
						}
					}
				}
				if(value > 0) {
					c.setValue(value);
					cells.add(c);
				}
			}
		}
		
		Collections.sort(cells, new CellComparator());
		
		cellList.put(towerName, cells);
	}
	
	private static double getDistance(Cell c1, Cell c2) {
		return Math.sqrt(Math.pow(c1.getX() - c2.getX(), 2) + Math.pow(c1.getY() - c2.getY(), 2));
	}
	
	public static ArrayList<Cell> get(String towerName) {
		return cellList.get(towerName);
	}
}
